﻿/**********************************************************
 ●项目：Smartkernel
 ●公司：智能核心信息技术研发中心
 ●作者：曹艳白
 ●邮箱：caoyanbai@gmail.com
 ●创建：2008-08-10
**********************************************************/
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Reflection;
using Smartkernel.Interfaces;

namespace Smartkernel
{
    /// <summary>
    /// 智能反射功能，提供反射的相关功能
    /// </summary>
    public static partial class SmartReflection
    {
        #region 方法调用
        /// <summary>
        /// 反射对象的方法，并调用
        /// </summary>
        /// <param name="methodName">方法名，区分大小写</param>
        /// <param name="target">对象</param>
        /// <param name="args">方法的参数</param>
        /// <returns>方法调用返回的结果</returns>
        public static object MethodInvoke(string methodName, object target, object[] args)
        {
            BindingFlags bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Static;

            return target.GetType().InvokeMember(methodName, bindingFlags, null, target, args, SmartCultureInfo.DefaultCultureInfo);
        }
        /// <summary>
        /// 反射对象的方法，并调用
        /// </summary>
        /// <param name="methodName">方法名，区分大小写</param>
        /// <param name="target">对象</param>
        /// <returns>方法调用返回的结果</returns>
        public static object MethodInvoke(string methodName, object target)
        {
            return MethodInvoke(methodName, target, null);
        }
        /// <summary>
        /// 反射对象的方法，并调用。注意，对象是通过类型自动创建的
        /// </summary>
        /// <param name="methodName">方法名，区分大小写</param>
        /// <param name="type">对象的类型</param>
        /// <param name="args">方法的参数</param>
        /// <returns>方法调用返回的结果</returns>
        public static object MethodInvoke(string methodName, Type type, object[] args)
        {
            return MethodInvoke(methodName, Activator.CreateInstance(type), args);
        }
        /// <summary>
        /// 反射对象的方法，并调用。注意，对象是通过类型自动创建的
        /// </summary>
        /// <param name="methodName">方法名，区分大小写</param>
        /// <param name="type">对象的类型</param>
        /// <returns>方法调用返回的结果</returns>
        public static object MethodInvoke(string methodName, Type type)
        {
            return MethodInvoke(methodName, Activator.CreateInstance(type), null);
        }
        #endregion
    }
    public static partial class SmartReflection
    {
        #region 获得类型的成员
        /// <summary>
        /// 获得某种类型的属性集合，包括公共属性和非公共属性，方法内部已实现高速缓存
        /// </summary>
        /// <param name="type">要反射的类型</param>
        /// <returns>属性的数组</returns>
        public static PropertyInfo[] GetProperties(Type type)
        {
            BindingFlags bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
            return type.GetProperties(bindingFlags);
        }
        /// <summary>
        /// 获得某种类型的字段集合，包括公共字段和非公共字段，方法内部已实现高速缓存
        /// </summary>
        /// <param name="type">要反射的类型</param>
        /// <returns>字段的数组</returns>
        public static FieldInfo[] GetFields(Type type)
        {
            BindingFlags bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
            return type.GetFields(bindingFlags);
        }
        /// <summary>
        /// 获得拥有某种特性标识的某种类型的属性集合，包括公共属性和非公共属性，方法内部已实现高速缓存
        /// </summary>
        /// <typeparam name="TAttribute">特性的类型</typeparam>
        /// <param name="type">要反射的类型</param>
        /// <returns>属性的数组</returns>
        public static PropertyInfo[] GetPropertiesWithAttribute<TAttribute>(Type type) where TAttribute : Attribute
        {
            BindingFlags bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;

            List<PropertyInfo> list = new List<PropertyInfo>();
            foreach (PropertyInfo propertyInfo in type.GetProperties(bindingFlags))
            {
                TAttribute attribute = (TAttribute)Attribute.GetCustomAttribute(propertyInfo, typeof(TAttribute), false);
                if (attribute != null)
                {
                    list.Add(propertyInfo);
                }
            }
            return list.ToArray();
        }
        /// <summary>
        /// 获得拥有某种特性标识的某种类型的字段集合，包括公共字段和非公共字段，方法内部已实现高速缓存
        /// </summary>
        /// <typeparam name="TAttribute">特性的类型</typeparam>
        /// <param name="type">要反射的类型</param>
        /// <returns>字段的数组</returns>
        public static FieldInfo[] GetFieldsWithAttribute<TAttribute>(Type type) where TAttribute : Attribute
        {
            BindingFlags bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;

            List<FieldInfo> list = new List<FieldInfo>();
            foreach (FieldInfo fieldInfo in type.GetFields(bindingFlags))
            {
                TAttribute attribute = (TAttribute)Attribute.GetCustomAttribute(fieldInfo, typeof(TAttribute), false);
                if (attribute != null)
                {
                    list.Add(fieldInfo);
                }
            }
            return list.ToArray();
        }
        #endregion
    }
    public static partial class SmartReflection
    {
        #region 类型转换
        /// <summary>
        /// 将字符串类型的对象转换为另外一种类型的对象
        /// </summary>
        /// <param name="source">待转换的对象</param>
        /// <param name="targetType">目标类型</param>
        /// <returns>转换的结果</returns>
        public static object ConvertTo(string source, Type targetType)
        {
            object result = null;
            if (targetType.GetInterface(typeof(ISmartConvertFromString).FullName) != null)
            {
                //如果实现了ISmartConvertFromString接口，则使用接口的方法转换
                result = Activator.CreateInstance(targetType);
                result = ((ISmartConvertFromString)result).ConvertFrom(source);
            }
            else if (targetType.IsEnum)
            {
                //如果目标类型是枚举，则按照枚举的方式解析
                result = Enum.Parse(targetType, source, true);
            }
            else if (targetType == typeof(TimeSpan))
            {
                //如果目标类型是时间间隔，按照字符到时间间隔的方式解析，时间解析为毫秒
                result = TimeSpan.FromMilliseconds(Convert.ToDouble(source, SmartCultureInfo.DefaultCultureInfo));
            }
            else if (targetType == typeof(List<string>))
            {
                //如果目标类型是列表，按照字符到列表的方式转换，字符串以“|”分隔
                List<string> list = new List<string>();
                list.AddRange(source.Split('|'));
                result = list;
            }
            else if (targetType == typeof(Color))
            {
                //如果目标类型是Color，则将源看作颜色值
                result = Color.FromName(source);
            }
            else
            {
                //其它目标类型的情况
                result = Convert.ChangeType(source, targetType, SmartCultureInfo.DefaultCultureInfo);
            }
            return result;
        }
        /// <summary>
        /// 转换为目标类型
        /// </summary>
        /// <typeparam name="TTargetType">目标类型</typeparam>
        /// <param name="source">源</param>
        /// <returns>转换的结果</returns>
        public static TTargetType ConvertTo<TTargetType>(string source)
        {
            return (TTargetType)ConvertTo(source, typeof(TTargetType));
        }
        /// <summary>
        /// 转换为目标类型
        /// </summary>
        /// <typeparam name="TSourceType">源类型</typeparam>
        /// <typeparam name="TTargetType">目标类型</typeparam>
        /// <param name="source">源</param>
        /// <returns>转换的结果</returns>
        public static TTargetType ConvertTo<TSourceType, TTargetType>(TSourceType source)
        {
            return (TTargetType)Convert.ChangeType(source, typeof(TTargetType), SmartCultureInfo.DefaultCultureInfo);
        }
        #endregion
    }
    public static partial class SmartReflection
    {
        #region 其他方法
        /// <summary>
        /// 通过一个源对象克隆一个新对象，每个属性和字段都和源对象相同
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="source">源对象</param>
        /// <returns>新的克隆对象</returns>
        public static T Clone<T>(T source)
        {
            Type type = typeof(T);
            T item = Activator.CreateInstance<T>();
            //克隆属性值
            foreach (PropertyInfo propertyInfo in GetProperties(type))
            {
                Object value = propertyInfo.GetValue(source, null);
                propertyInfo.SetValue(item, value, null);
            }
            //克隆字段值
            foreach (FieldInfo fieldInfo in GetFields(type))
            {
                Object value = fieldInfo.GetValue(source);
                fieldInfo.SetValue(item, value);
            }
            return item;
        }
        #endregion
    }
}
